package com.gpf.common;

import java.util.LinkedHashMap;

import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

/**@Configuration 注解描述的类为一个配置对象,
 * 此对象也会交给spring管理
 */
@Configuration
public class SpringShiroConfig {
	/**配置记住我管理器对象*/
	@Bean
	public RememberMeManager rememberMeManager() {
		CookieRememberMeManager rManager=new CookieRememberMeManager();
		SimpleCookie cookie=new SimpleCookie("rememberMe");
		cookie.setMaxAge(7*24*60*60);
		rManager.setCookie(cookie);
		return rManager;
	}
	
	/**配置shiro框架中的CacheManager对象,用于缓存用户权限*/
	@Bean
	public CacheManager shiroCacheManager() {
		return new MemoryConstrainedCacheManager();
	}
	/**
	 * 	SecurityManager是Shiro框架的核心,用于实现认证,授权等功能.
	 * 	说明:Spring容器中整合三方Bean对象时,可以将其Bean对象的创建放在一个方法中,
	 *	 然后使用@Bean注解进行描述,Spring容器管理bean对象时就会将方法名作为key
	 *	对Bean对象进行存储.
	 */
	//添加SecurityManager配置
	//@Bean功能类似@Component,@Service,...
	@Bean
	public SecurityManager securityManager(Realm realm,CacheManager cacheManager,RememberMeManager rememberMeManager) {
		DefaultWebSecurityManager sManager=new DefaultWebSecurityManager();
		sManager.setRealm(realm);
		sManager.setCacheManager(cacheManager);
		sManager.setRememberMeManager(rememberMeManager);//记住我
		return sManager;
	}
	//添加ShiroFilterFactoryBean对象的配置。通过此对象设置资源匿名访问、认证访问。
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		//构建对象，此对象负责创建过滤器工厂
		ShiroFilterFactoryBean sfBean=new ShiroFilterFactoryBean();
		//关联SecurityManage（要借助此对象那个对url进行认证分析）
		sfBean.setSecurityManager(securityManager);
		//添加登录url的设置
		sfBean.setLoginUrl("/doLoginUI");
		//定义map指定请求过滤规则(哪些资源允许匿名访问,哪些必须认证访问)
		LinkedHashMap<String,String> map= new LinkedHashMap<>();
		//静态资源允许匿名访问:"anon"
		map.put("/bower_components/**","anon");
		map.put("/build/**","anon");
		map.put("/dist/**","anon");
		map.put("/plugins/**","anon");
		//对/user/doLogin这个路径进行匿名访问的配置
		map.put("/user/doLogin","anon");
		//退出登录
		map.put("/doLogout","logout"); //"logout"对应shiro中的一个默认filter
		//除了匿名访问的资源,其它都要认证("authc")后访问
		//map.put("/**","authc");
		map.put("/**","user");//记住我(user表示认证可从cookie取信息来实现)
		sfBean.setFilterChainDefinitionMap(map);
		return sfBean;
	}
	@Bean
	public LifecycleBeanPostProcessor   lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}
	@DependsOn("lifecycleBeanPostProcessor")
	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		return new DefaultAdvisorAutoProxyCreator();
	}
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor (SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor advisor=new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}
}
